#!/usr/bin/python -O
# -*- coding: utf-8 -*-


import sys
import signal
import time
import socket
import struct
import irc_server
import irc_protocol
import re

import plugins
from irc_config import Config

########################################
##
## Handles ctrl-c, break, SIGINT
##
## on first call, sets global variable
## break_detected to true, then restores
## the original handler, and ctrl-c
## works as normal
##
## (so if you badly need to stop the
## process, you can press ctrl-c repeatedly
## and that will crash the process)
##
def break_handler(signum, frame):
    global break_detected
    global previous_handler

    print "\n=== caught SIGINT!\n"
    sys.stdout.flush()

    break_detected=True
    signal.signal(signum,previous_handler)



########################################
##
## parses the !command and calls the
## appropriate plugin-function to process
## it.
##
def process_command( server, command ):

    if command[1]=='PRIVMSG':
        # checks if the text looks like a command
        if (command[3]!=''):
            if (command[3][0]=='!'):
                # looks like a command
                #
                command_line = command[3].split(' ') # splits in words
                command_name = command_line[0][1:]   # first word, skips !

                if plugins.commands.has_key(command_name):
                    plugins.commands[command_name](server,
                                                   command,
                                                   plugins.command_help,
                                                   plugins.authenticate);


                # only command that's always
                # available
                #
                if command_name=='quit':
                    if plugins.authenticate.user_level(command[0])>=90:
                        global break_detected
                        break_detected=True
                    else:
                        server.send(
                            irc_protocol.reply(
                                command, "insufficient access level." ))

    else:
        pass # some other type of message
             # we are not interested in


########################################
##
## Trackers are routines that are used
## to monitor events such as parting,
## joining, and others. Unlike commands,
## they do not have to be directed at
## the bot
##
def process_trackers( server, command ):
    for tracker in plugins.trackers:
        tracker(server, command)

########################################
##
##
##
def main():
    global config

    config = Config()

    ##########################
    #
    # sets ^c handler to keep threads from
    # getting sigint and crash while still
    # not stopping the program
    #
    global previous_handler
    global break_detected

    previous_handler = signal.signal(signal.SIGINT,signal.SIG_IGN)
    signal.signal(signal.SIGINT,break_handler)
    break_detected=False

    # TODO: Fork for each new server connection.
    if len(config.servers()) > 1:
        raise Exception("Multiple server not supported, yet")

    ##########################
    #
    # connects and stuff
    #
    for server_config in config.servers():
        server = irc_server.Server() # a new server
        server.load_filters("log_filters.dat")

        if server.connect(server_config.server_host,
                          server_config.server_port,
                          server_config.server_nick,
                          plugins.version.bakeneko_version):

            # post-log script
            # TODO: Make this a plugin.
            server.send_multiline(["PRIVMSG nickserv :identify 7ggx8n4w"])

            time.sleep(5)

            # joins channels
            server.join(server_config.channels)

            while not break_detected:

                sys.stdout.flush()
                lines = server.receive()
            
                for line in lines:
                    # deals with pong at this level:
                    # it should be done without user's
                    # intervention
                    parsed=irc_protocol.parse(line);
                
                    # parses commands
                    if parsed[1]=="PING":
                        # processes PING here because
                        # it's the only command that cannot
                        # be ignored.
                        server.send("PONG "+" ".join(parsed[2:]))
                    else:
                        process_command( server, parsed );
                        process_trackers( server, parsed );
    
            server.disconnect("Absurd!")
            plugins.authenticate.save_users()
        else:
            print "=== cannot connect!"

# linking to explicit main
if __name__ == "__main__":
    main()
